package business.article.managers;

import java.util.ArrayList;

import dbExceptions.BadComboException;
import dbExceptions.DataBaseErrorException;
import dbExceptions.MissingComboException;
import persistence.article.articleDAO.ArticleDAO;
import persistence.category.categoryDAO.CategoryDAO;
import persistence.combo.comboDAO.ComboDAO;
import persistence.ingredient.ingredientDAO.IngredientDAO;
import article.entities.ArticleVO;
import article.entities.CategoryVO;
import article.entities.ComboVO;
import article.entities.IngredientVO;
import article.exceptions.BadArticleException;
import article.exceptions.BadCategoryException;
import article.exceptions.IncompleteArticleException;
import article.exceptions.MissingArticleException;
import article.exceptions.MissingCategoryException;
import article.exceptions.NotHereException;
import business.article.entities.Article;
import business.article.entities.Category;
import business.article.entities.Combo;
import business.article.entities.Ingredient;
import business.article.interfaces.ArticleMgt;

public class ArticleMgr implements ArticleMgt {

	/**
	 * singleton
	 */
	private static ArticleMgr instance = null;

	private ArticleMgr() {
	}

	public static ArticleMgr getInstance() {
		if (instance == null)
			instance = new ArticleMgr();
		return instance;
	}

	/**
	 * singleton end
	 */

	// METODO DE ARTICLE

	public void addArticle(ArticleVO artNew) throws IncompleteArticleException,
			MissingCategoryException, DataBaseErrorException,
			BadCategoryException, MissingArticleException {
		if (artNew != null && artNew.getName() != null
				&& artNew.getPrice() >= 0) {
			ArticleDAO aux = ArticleDAO.getInstance();
			aux.addArticle(new Article(artNew));
		} else {
			throw new IncompleteArticleException("Faltan datos");
		}

	}

	public void updateArticle(ArticleVO artUpt) throws NotHereException,
			IncompleteArticleException, MissingCategoryException,
			DataBaseErrorException, BadCategoryException,
			MissingArticleException, BadArticleException {
		if (artUpt != null && artUpt.getName() != null
				&& artUpt.getPrice() >= 0 && artUpt.getPrimaryKey() > 0) {
			ArticleDAO aux = ArticleDAO.getInstance();
			aux.updateArticle(new Article(artUpt));
		} else {
			throw new IncompleteArticleException("Faltan datos");
		}

	}

	public void deleteArticle(ArticleVO artDel) throws NotHereException,
			MissingArticleException, BadArticleException,
			DataBaseErrorException {
		ArticleDAO aux = ArticleDAO.getInstance();
		if (artDel != null && artDel.getPrimaryKey() > 0)
			aux.deleteArticle(new Article(artDel));
		else
			throw new NotHereException(
					"No se encuentra el articulo en cuestion");
	}

	public ArticleVO[] getArticles() {
		ArticleDAO aux = ArticleDAO.getInstance();
		return this.toVOsA(aux.getArticles());
	}
	
	@Override
	public ArrayList<ArticleVO> getAllArticles() {
		ArticleDAO aux = ArticleDAO.getInstance();
		return this.toVOsAA(aux.getAllArticles());
	}

	// METODO DE INGREDIENT

	public IngredientVO[] getAllIngredients() {
		return this.toVOsI(IngredientDAO.getInstance().getAllIngredients());
	}

	public IngredientVO[] getInStockIngredients() {
		return this.toVOsI(IngredientDAO.getInstance().getInStockIngredients());
	}

	public IngredientVO[] getOutStockIngredients() {
		return this
				.toVOsI(IngredientDAO.getInstance().getOutStockIngredients());
	}

	public void newIngredient(String name) {
		IngredientDAO.getInstance().newIngredient(name);
	}

	public void addOutOfStock(ArrayList<IngredientVO> ingredientes) {
		IngredientDAO.getInstance().addOutOfStock(this.toAI(ingredientes));
	}

	public void addInStock(ArrayList<IngredientVO> ingredientes) {
		IngredientDAO.getInstance().addInStock(this.toAI(ingredientes));
	}

	// METODOS DE CATEGORY

	public CategoryVO[] getCategories() {
		return this.toVOsC(CategoryDAO.getInstance().getCategories());
	}

	public void newCategory(String name) {
		CategoryDAO.getInstance().newCategory(name);
	}

	// COMBOS
	public ComboVO[] getComos() {
		return this.toVOsComb(ComboDAO.getInstance().getCombos());
	}

	@Override
	public void newCombo(ComboVO comb) throws MissingCategoryException,
			MissingComboException, BadCategoryException {
		if (comb != null) {
			ComboDAO.getInstance().newCombo(new Combo(comb));
		} else {
			throw new MissingComboException("Falta algo");
		}

	}

	@Override
	public void deleteCombo(ComboVO comb) throws MissingArticleException,
			BadArticleException, DataBaseErrorException {
		if (comb != null && comb.getPrimaryKey() != 0)
			ComboDAO.getInstance().deleteCombo(new Combo(comb));
	}

	@Override
	public void updateCombo(ComboVO comb) throws MissingComboException,
			BadComboException, BadCategoryException, MissingCategoryException,
			DataBaseErrorException {
		if (comb != null && comb.getPrimaryKey() != 0)
			ComboDAO.getInstance().updateCombo(new Combo(comb));

	}

	// CONVERTIR LOS ARRAYS DE ELEMENTOS

	private IngredientVO[] toVOsI(Ingredient[] ing) {
		IngredientVO[] temp = (ing != null) ? new IngredientVO[ing.length]
				: null;
		int i = 0;
		for (Ingredient e : ing) {
			temp[i] = e.toVO();
			i++;
		}
		return temp;
	}

	public ArrayList<Ingredient> toAI(ArrayList<IngredientVO> ing) {
		ArrayList<Ingredient> temp = new ArrayList<Ingredient>();
		for (IngredientVO e : ing)
			temp.add(new Ingredient(e));
		return temp;
	}

	private CategoryVO[] toVOsC(Category[] cat) {
		CategoryVO[] temp = (cat != null) ? new CategoryVO[cat.length] : null;
		int i = 0;
		for (Category e : cat) {
			temp[i] = e.toVO();
			i++;
		}
		return temp;
	}

	private ArticleVO[] toVOsA(Article[] art) {
		ArticleVO[] temp = (art != null) ? new ArticleVO[art.length] : null;
		int i = 0;
		for (Article e : art) {
			temp[i] = e.toVO();
			i++;
		}
		return temp;
	}
	
	private ArrayList<ArticleVO> toVOsAA(ArrayList<Article> art){
		ArrayList<ArticleVO> temp = new ArrayList<ArticleVO>();
		for(Article o : art){
			temp.add(o.toVO());
		}return temp;
	}

	private ComboVO[] toVOsComb(Combo[] comb) {
		ComboVO[] temp = (comb != null) ? new ComboVO[comb.length] : null;
		int i = 0;
		for (Combo e : comb) {
			temp[i] = e.toVO();
			i++;
		}
		return temp;
	}


}
